package com.linkallcloud.web.support;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import com.linkallcloud.cache.redis.box.RedisTokenBox;
import com.linkallcloud.core.lang.Mirror;
import com.linkallcloud.core.log.Log;
import com.linkallcloud.core.log.Logs;
import com.linkallcloud.core.www.ISimpleUser;
import com.linkallcloud.web.utils.Controllers;

public abstract class AbstractSessionUserArgumentResolver<U extends ISimpleUser>
        implements HandlerMethodArgumentResolver {
    protected final Log log = Logs.get();

    protected Mirror<U> mirror;

    @Autowired
    private RedisTokenBox tokenBox;

    @SuppressWarnings("unchecked")
    public AbstractSessionUserArgumentResolver() {
        super();
        try {
            mirror = Mirror.me((Class<U>) Mirror.getTypeParams(getClass())[0]);
        } catch (Throwable e) {
            if (log.isWarnEnabled()) {
                log.warn("!!!Fail to get TypeParams for self!", e);
            }
        }
    }

    public Class<U> getSessionUserClass() {
        return (null == mirror) ? null : mirror.getType();
    }

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.getParameterType().isAssignableFrom(ISimpleUser.class);
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
            NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        return Controllers.getSessionUser(webRequest.getNativeRequest(HttpServletRequest.class), tokenBox,
                getSessionUserClass());
    }

}
